#!/usr/bin/python

## mkboard.py -- atmel pio mux utility
##
## Copyright 2006, Brian Swetland.  All rights reserved.
## See provided LICENSE file or http://frotz.net/LICENSE for details.
##

import os, sys, string

# pindef -> num, out, pull, pio, sela, selb

reg_output_disable = 0
reg_output_enable = 0
reg_pullup_disable = 0
reg_pullup_enable = 0
reg_pio_disable = 0
reg_pio_enable = 0
reg_select_a = 0
reg_select_b = 0

def setup_registers(pindef):
    global reg_output_disable
    global reg_output_enable
    global reg_pullup_disable
    global reg_pullup_enable
    global reg_pio_disable
    global reg_pio_enable
    global reg_select_a
    global reg_select_b
    
    (num, out, pull, pio, sela, selb) = pindef

    bit = 1 << num
    
    if out:
        reg_output_enable |= bit
        reg_output_disable &= (~bit)
    else:
        reg_output_enable &= (~bit)
        reg_output_disable |= bit

    if pull:
        reg_pullup_enable |= bit
        reg_pullup_disable &= (~bit)
    else:
        reg_pullup_enable &= (~bit)
        reg_pullup_disable |= bit

    if pio:
        reg_pio_enable |= bit
        reg_pio_disable &= (~bit)
    else:
        reg_pio_enable &= (~bit)
        reg_pio_disable |= bit

    if sela:
        reg_select_a |= bit
    if selb:
        reg_select_b |= bit

def import_pindef(fn):
    pass

def read_pins_def(fn, table):
    output = ""
    fd = open(fn,'r')
    for line in fd.xreadlines():
        line = line.split('#')[0].strip()
        if not line: continue

        (gpio,pa,pb) = line.split()
        num = int(gpio[2:])

        table[gpio+"_IN"] = (num, 0, 0, 1, 0, 0)
        table[gpio+"_IN_PULLUP"] = (num, 0, 1, 1, 0, 0)
        table[gpio+"_OUT"] = (num, 1, 0, 1, 0, 0)
        table[gpio+"_"+pa] = (num, 0, 0, 0, 1, 0)
        table[gpio+"_"+pb] = (num, 0, 0, 0, 0, 1)

    return output
    
def read_board_def(fn, table):
    pins = {}
    output = ""
    for n in range(0,32):
        pins[n] = ''
        
    fd = open(fn,'r')
    for line in fd.xreadlines():
        line = line.split('#')[0].strip()
        if not line: continue

        if len(line.split('=')) == 2:
            (line,func) = line.split('=')
            line = line.strip()
            func = func.strip()
        else:
            func = ''
            
        parts = line.split()
        if len(parts) < 2:
            print "ERROR: invalid definition '%s'" % line
            sys.exit(1)

        if not func:
            if (parts[1] == 'IN') or (parts[1] == 'OUT'):
                func = parts[0]
            else:
                func = parts[1]
            
        pin = string.join(parts,"_")
        
        if not table.has_key(pin):
            print "ERROR: pin '%s' does not exist" % pin
            sys.exit(1)

        pindef = table[pin]
        num = pindef[0]
        if pins[num]:
            print "ERROR: pin '%s' conflicts with pin '%s'" % (pin, pins[num])
            sys.exit(1)
        pins[num] = pin

        setup_registers(pindef)
        output += "#define PIN_%-12s (1 << %d)\n" % (func, num)

    return output

table = {}
output = ""
    
for fn in sys.argv[1:]:
    if fn.endswith('.pins'):
        if table:
            print "ERROR: only one pin definition file allowed"
            sys.exit(1)
        output = read_pins_def(fn, table)
        continue
    
    if fn.endswith('.def'):
        if not table:
            print "ERROR: must specify a pin definition file first"
            sys.exit(1)

        reg_output_disable = 0xffffffffL
        reg_output_enable =  0L
        reg_pullup_disable = 0L
        reg_pullup_enable =  0xffffffffL
        reg_pio_disable =    0L
        reg_pio_enable =     0xffffffffL
        reg_select_a =       0L
        reg_select_b =       0L
            
        output = read_board_def(fn, table)
        fd = open(fn[:-4] + ".h", 'w')
        fd.write("/* DO NOT EDIT -- AUTOGENERATED FROM '%s' */\n\n" % fn)
        fd.write("#ifndef __BOARD_DEFINITION_FILE__\n")
        fd.write("#define __BOARD_DEFINITION_FILE__\n\n")
        fd.write(output)
        fd.write("\n")
        fd.write("#define BOARD_OUTPUT_DISABLE 0x%08x\n" % reg_output_disable)
        fd.write("#define BOARD_OUTPUT_ENABLE  0x%08x\n" % reg_output_enable)
        fd.write("#define BOARD_PULLUP_DISABLE 0x%08x\n" % reg_pullup_disable)
        fd.write("#define BOARD_PULLUP_ENABLE  0x%08x\n" % reg_pullup_enable)
        fd.write("#define BOARD_PIO_DISABLE    0x%08x\n" % reg_pio_disable)
        fd.write("#define BOARD_PIO_ENABLE     0x%08x\n" % reg_pio_enable)
        fd.write("#define BOARD_SELECT_A       0x%08x\n" % reg_select_a)
        fd.write("#define BOARD_SELECT_B       0x%08x\n" % reg_select_b)
        fd.write("\n#endif\n")
        fd.close()
        continue

    print "ERROR: what is '%s'?" % fn
    sys.exit(1)
    
    

